<?php
/**
 * I-Framework的原生类
 * 
 * 最底层的工具类，不使用任何其他I-Framework中的类.
 * 
 * 仅限I-Framework内部调用，意味着其中的方法在不同版本中可能有较大变动，用户如果直接调用该类，将会有很大的风险.
 *
 * @version $Id: native.php 312 2008-04-23 16:29:38Z iwind $
 * @package util.core
 */
class native {
	private static $defaultPackages = array(".");
	private static $cachedClasses = array();
	private static $includedFiles = array();
	
	private static function getCachedClassKey() {
		return "class://native//" . IFRAMEWORK_APP_ROOT . "/cachedClass";
	}
	
	/**
	 * 导入类
	 *
	 * @param string $className 类名称
	 * @throws Exception
	 */
	public static function import($className) {
		if (self::loadCachedClass($className)) {
			return;
		}
		
		$classFileName = IFRAMEWORK_DIRECTORY . "/" . self::getClassFile($className);
		$files = glob($classFileName);
		if (!empty($files)) {
			native::load($className, $files);
			return;
		}
		throw new Exception("can't find class '{$className}'");
	}
	
	/**
	 * 根据类名称取得类文件路径
	 *
	 * @param string $className 类名称
	 * @return string
	 */
	public static function getClassFile($className) {		
		return str_replace(".", "/", $className) . ".php";
	}
	
	/**
	 * 取得默认的包名
	 *
	 * @return array
	 */
	public static function getDefaultPackages() {
		$packages = array();
		foreach (self::$defaultPackages as $key=>$package) {
			if ($package != ".") {
				$packages[$key] = IFRAMEWORK_DIRECTORY . "/" . $package;
			}
			else {
				$packages[$key] = $package;
			}
		}
		return $packages;
	}
	
	/**
	 * 根据类的完整名称（包括包名）取得类的名称
	 *
	 * @param string $className 类的完整名称
	 * @return string
	 */
	public static function getRealClassName($className) {
		if (gettype($className) != "string") {
			return;
		}
		if (strstr($className, ".")) {
			$glues = explode(".", $className);
			return array_pop($glues);
		}
		return $className;
	}
	
	/**
	 * 将类路径加入缓存
	 * 
	 * 在APC有效的环境下起作用
	 *
	 * @param string $className 类名称
	 * @param string $classPath 类的路径
	 */
	public static function addCachedClass($className, $classPath) {
		if (IFRAMEWORK_APC_ENABLED) {
			$classes = apc_fetch(self::getCachedClassKey());
			if (!is_array($classes)) {
				$classes = array();
			}
			$classes[$className] = $classPath;
			apc_store(self::getCachedClassKey(), $classes);
		}
	}
	
	/**
	 * 从缓存中加载类
	 *
	 * 在APC有效的环境下起作用
	 * 
	 * @param string $className 类名称
	 * @return boolean
	 */
	public static function loadCachedClass($className) {
		if (class_exists(self::getRealClassName($className), false)) {
			return true;
		}
		global $SYSTEM_CLASSES;
		if (isset($SYSTEM_CLASSES[$className])) {
			require(IFRAMEWORK_DIRECTORY . $SYSTEM_CLASSES[$className]);
			//编译
//			echo $className . "<br/>";
//			var_dump(ICompiler::getCurrentProcess() != null);
			if (class_exists("ICompiler", false) && ICompiler::getCurrentProcess()) {
				ICompiler::getCurrentProcess()->mergeFile($className, IFRAMEWORK_DIRECTORY . $SYSTEM_CLASSES[$className]);
				ICompiler::getCurrentProcess()->commit();
			}
			
			return true;
		}
		
		$success = false;
		//echo $className . "<br/>";
		if (IFRAMEWORK_APC_ENABLED) {
			if (!empty(self::$cachedClasses)) {
				$classes = self::$cachedClasses;	
			}
			else {
				$classes = apc_fetch(self::getCachedClassKey());
			}
			if (!is_array($classes)) {
				return false;
			}
			//如果文件存在
			if (isset($classes[$className])) {
				$classFiles = $classes[$className];
				if (!is_array($classFiles)) {
					$classFiles = array($classFiles);
				}
				foreach ($classFiles as $classFile) {
					if (is_file($classFile) && !in_array($classFile, self::$includedFiles)) {
						require $classFile;
						self::$defaultPackages[] = dirname(realpath($classFile));
						self::$includedFiles[] = $classFile;
					}
					else {
						unset($classes[$className]);
						self::$cachedClasses = $classes;
						apc_store(self::getCachedClassKey(), $classes);
						return false;
					}
				}
				return true;
			}
			
			//从所有文件名中匹配
			foreach ($classes as $classFiles) {
				if (!empty($classFiles) && is_array($classFiles)) {
					foreach ($classFiles as $classFile) {
						$basename = basename($classFile);
						if ($basename == $className . ".php") {
							if (!in_array($classFile, self::$includedFiles)) {
								require $classFile;
								native::addCachedClass($className, $classFile);
								self::$includedFiles[] = $classFile;
								return true;
							}
						}
					}
				}
			}
		}
		return $success;
	}
	
	/**
	 * 取得缓存的类的列表
	 * 
	 * 在APC有效的环境下起作用
	 *
	 * @return array
	 */
	public static function getCachedClassList() {
		if (IFRAMEWORK_APC_ENABLED) {
			return apc_fetch(self::getCachedClassKey());
		}
		return array();
	}
	
	/**
	 * 从文件列表中查找并加载指定的类
	 *
	 * @param string $className 类名称
	 * @param array/string $classFiles 文件列表
	 */
	public static function load($className, $classFiles) {
		$realClassName = self::getRealClassName($className);
		if (class_exists($realClassName, false)) {
			return true;
		}
		if (!is_array($classFiles)) {
			$classFiles = array($classFiles);
		}
		foreach ($classFiles as $key=>$classFile) {
			if (is_file($classFile) && !in_array($classFile, self::$includedFiles)) {
				require $classFile;
				self::$includedFiles[] = $classFile;
				if (class_exists("ICompiler", false) && ICompiler::getCurrentProcess()) {
					ICompiler::getCurrentProcess()->mergeFile($realClassName, $classFile);
					ICompiler::getCurrentProcess()->commit();
				}
			}
			else {
				unset($classFiles[$key]);
			}
		}
		native::addCachedClass($className, $classFiles);
	}
	
	/**
	 * 判断一个名称是否适合作为变量名
	 *
	 * @param string $variableName 变量名
	 * @return boolean
	 */
	public static function isValidVariableName($variableName) {
		if (preg_match("/^[_a-z]\\w*$/i", $variableName)) {
			return true;
		}
		return false;
	}
	
	/**
	 * 判断一个类名称（包括包名）是否可用
	 *
	 * @param string $className 类名称（可以含包名，如 a.b.c.ExampleClass）
	 * @return boolean
	 * @since 0.0.3
	 */
	public static function isValidClassName($className) {
		if (preg_match("/^([_a-z]\\w*\\.)*([_a-z]\\w*)$/i", $className)) {
			return true;
		}
		return false;
	}
	
	/**
	 * 判断一个路径是否是绝对路径
	 *
	 * @param string $path 路径
	 * @return boolean
	 * @since 0.0.3
	 */
	public static function isAbsolutePath($path) {
		$path = trim($path);
		if (preg_match("/^\\//", $path) || preg_match("/^\\\\/", $path) || preg_match("/^\\w:\\\\/", $path)) {
			return true;
		}
		return false;
	}	
	
	/**
	 * 将名称转换为C的编码风格
	 * 
	 * 字母小写，单词之间有中划线<br/>
	 * loadXmlConfig --> load_xml_config
	 *
	 * @param string $name 名称
	 * @return string
	 * @since 0.1
	 */
	public static function nameToC($name) {
		$name = preg_replace("/[A-Z]/", "_\\0", $name);
		return strtolower(trim($name, "_"));
	}
	
	/**
	 * 将名称转换为Java的编程风格
	 *
	 * 首字母小写，其余单词的首字母大写<br/>
	 * load_xml_config --> loadXmlConfig
	 * 
	 * @param string $name 名称
	 * @return string
	 * @since 0.1
	 */
	public static function nameToJava($name) {
		$name = preg_replace("/_([a-zA-Z])/e", "strtoupper('\\1')", $name);
		return $name;
	}
}


?>